package org.jrpc.client3;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.jrpc.base.IClient;
import org.jrpc.base.ResultResponse;
import org.jrpc.common.baen.RpcRequest;
import org.jrpc.common.baen.RpcResponse;
import org.jrpc.common.codec.RpcDecoder;
import org.jrpc.common.codec.RpcEncoder;
import org.jrpc.core.factory.JrpcConfiguration;
import org.springframework.beans.factory.InitializingBean;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by chenyuncong on 2019/4/16.
 */
public class JrpcClient extends Thread implements IClient,InitializingBean {
    private EventLoopGroup loop = new NioEventLoopGroup();

    private ConcurrentHashMap<String,ResultResponse> map=new ConcurrentHashMap<>();

    private JrpcClientHandler rpcClientHandler;;

//    private final String host;

//    private final int port;

    private JrpcConfiguration jrpcConfiguration;



    /*public JRpcClient(String host,int port) {
        this.host = host;
        this.port = port;
    }*/

    public JrpcClient(JrpcConfiguration jrpcConfiguration) {
        this.jrpcConfiguration = jrpcConfiguration;
    }
    @Override
    public ResultResponse put(RpcRequest request) {
        try {
            return rpcClientHandler.sendMsg(request);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public RpcResponse init(EventLoopGroup eventLoop) throws Exception {
        return null;
    }

    public Bootstrap createBootstrap(Bootstrap bootstrap, EventLoopGroup eventLoop) {
        if (bootstrap != null) {
            rpcClientHandler = new JrpcClientHandler(this,this.map);
            bootstrap.group(eventLoop);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    pipeline.addLast(new RpcEncoder(RpcRequest.class)); // 编码 RPC 请求
                    pipeline.addLast(new RpcDecoder(RpcResponse.class)); // 解码 RPC 响应
                    pipeline.addLast(rpcClientHandler); // 处理 RPC 响应
                }
            });
            bootstrap.remoteAddress(this.jrpcConfiguration.getHost(), Integer.parseInt(this.jrpcConfiguration.getPort()));
            bootstrap.connect().addListener(new ConnectionListener(this));
        }
        return bootstrap;
    }

    @Override
    public void run() {
        createBootstrap(new Bootstrap(), loop);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.start();
    }
}
